import routerLink from "./components/routerLink";
import routerView from "./components/routerView";
import { createMatch } from "./createMatch.js";

import Vue from "vue";
import { HashHistory } from "./history/hash";
import { HtmlHistory } from "./history/html";

export default class VueRouter {
  constructor(options = {}) {
    // vue-router 核心 match 核心

    this.match = createMatch(options.routes || []);
    this.beforeHooks = [];
    // 核心2 浏览器路由管理
    // 1.获取模式
    options.mode = options.mode || "hash";
    // 判断
    switch (options.mode) {
      case "hash":
        this.history = new HashHistory(this);
        break;
      case "history":
        this.history = new HtmlHistory(this);
    }

    // console.log(this.history, "HashHistory");
  }
  beforeEach(fn) {
    this.beforeHooks.push(fn);
  }
  push(locations) {
    // this.history.transitionsTo(locations);
    // 通过hash
    this.history.push(locations);
  }
  init(app) {
    // 根据路由找到组件  跳转和监听
    // console.log("init");
    //  获取当前的路由
    const history = this.history;

    history.listen((route) => {
      app._route = route;
    });
    // 跳转
    const setUpHashLister = () => {
      history.setUpLister(); // 监听路由的变化
    };
    history.transitionsTo(history.getCurrentLocation(), setUpHashLister);
  }
}

VueRouter.install = (_Vue) => {
  // console.log("_vuerouter");
  const vm = _Vue;
  vm.component("router-link", routerLink);
  vm.component("router-view", routerView);

  // 给每个组件添加实例 router 实例
  Vue.mixin({
    // 组件是父子关系
    beforeCreate() {
      if (this.$options.router) {
        // console.log(this.$options.router, "555");
        //如果是根实例
        this._router = this.$options.router; // 将router实例 放到根实例上
        this._routerRoot = this;
        this._router.init(this);

        // console.log(this, "当前的实力");
        // 变成响应式 current
        Vue.util.defineReactive(this, "_route", this._router.history.current);
        // console.log(this);
      } else {
        this._routerRoot = this.$parent && this.$parent._routerRoot;
      }
    },
  });

  // 代理 this.$route 属性 this.$router
  Object.defineProperty(Vue.prototype, "$router", {
    get() {
      return this._routerRoot._router;
    },
  });

  Object.defineProperty(Vue.prototype, "$route", {
    get() {
      return this._routerRoot._route;
    },
  });
};
